package main

import (
	"bytes"
	"crypto/ecdsa"
	"crypto/elliptic"
	"crypto/rand"
	"crypto/x509"
	"encoding/gob"
	"encoding/hex"
	"encoding/pem"
	"fmt"
	"github.com/btcsuite/btcutil/base58"
	"os"
)

func main() {
	generateEccKeypair(`./privateEccKey.pem`,`./publicEccKey.pem`)
}
/*
传入私钥文件路径 用于保存
 */
func generateEccKeypair(privatefile1Name,publicfile1Name string)  {
	// 选择一个椭圆
	curve:=elliptic.P256()
	// 使用ecdsa包 创建私钥
	/*
	func GenerateKey
	GenerateKey函数生成一对
	func GenerateKey(c elliptic.Curve, rand io.Reader) (priv *PrivateKey, err error)
	 */
	privateKey,err:=ecdsa.GenerateKey(curve,rand.Reader)
	if err != nil {
		panic(err)
	}

	// 使用x509编码
	derText,err:=x509.MarshalECPrivateKey(privateKey)
	if err != nil {
		panic(err)
	}
	
	// 写入pem。block
	block1:=pem.Block{
		Type:    "VOCALOID ECC private key",
		Headers: nil,
		Bytes:   derText,
	}
	// pem。encode
	file1, err := os.Create(privatefile1Name)
	if err != nil {
		panic(err)
	}
	err = pem.Encode(file1, &block1)
	if err != nil {
		panic(err)
	}
	fmt.Println("++++++++++++++++++++++开始生成公钥+++++++++++++++++++++++++")
	/**
	获取公钥
	*/
	publicKey := privateKey.PublicKey
	pubDerText,err:=x509.MarshalPKIXPublicKey(&publicKey)
	if err != nil {
		panic(err)
	}
	block2:=pem.Block{
		Type:    "VOCALOID ECC public key",
		Headers: nil,
		Bytes:   pubDerText,
	}
	file2, err := os.Create(publicfile1Name)
	if err != nil {
		panic(err)
	}
	err = pem.Encode(file2, &block2)
	if err != nil {
		panic(err)
	}



	//测试将私钥转为[]byte
	//将接口文件明确注册一下
	gob.Register(elliptic.P256())
	//gob.Register(elliptic.Curve)
	var buffer bytes.Buffer

	encoder:=gob.NewEncoder(&buffer)
	err=encoder.Encode(privateKey)
	if err!=nil {
		fmt.Println("钱包序列化失败！,",err)
		panic("gob编码错误！")
	}

	content:=buffer.Bytes()
	fmt.Println("编码私钥内容为：",content)
	fmt.Println("string编码私钥内容为：",hex.EncodeToString(content))
	fmt.Println("直接base58编码私钥内容为：",base58.Encode(content))

	fmt.Println("x509编码私钥内容为：",derText)
	fmt.Println("x509-hex编码私钥内容为：",hex.EncodeToString(derText))

	fmt.Println("==========编码坐标===============")
	privKeyByte:=privateKey.D.Bytes()
	puKeyByte := append(privateKey.X.Bytes(), privateKey.Y.Bytes()...)
	fmt.Println("==========私钥===============")
	fmt.Println("直接int转编码私钥内容为：",privKeyByte)
	fmt.Println("直接int-hex编码私钥内容为：",hex.EncodeToString(privKeyByte))
	fmt.Println("直接base58编码私钥内容为：",base58.Encode(privKeyByte))
	fmt.Println("==========公钥===============")
	fmt.Println("直接int转编码公钥内容为：",puKeyByte)
	fmt.Println("直接int-hex编码公钥内容为：",hex.EncodeToString(puKeyByte))
	fmt.Println("直接base58编码公钥内容为：",base58.Encode(puKeyByte))
}
